Skip to content

security: redact private key material from SigningKey repr/str#494

Open
OscarOzaine wants to merge 2 commits into
Python-Cardano:mainfrom
OscarOzaine:security/redact-signing-key-repr
Open

security: redact private key material from SigningKey repr/str#494
OscarOzaine wants to merge 2 commits into
Python-Cardano:mainfrom
OscarOzaine:security/redact-signing-key-repr

Conversation

@OscarOzaine

@OscarOzaine OscarOzaine commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

The problem

Calling repr() or str() on a signing key returned its full JSON, including the raw private key in the cborHex field. That meant secret keys could leak into:

  • log files (anything that logs an object)
  • exception tracebacks
  • debugger / REPL output

…without the developer ever intending to export the key.

The fix

  • Signing keys (SigningKey, ExtendedSigningKey, and their subclasses) now print a redacted form instead of their secret material:

    <PaymentSigningKey type='PaymentSigningKey' hash=a1b2c3d4e5f6a7b8 [REDACTED]>
    

    The hash= value is a short, non-reversible fingerprint derived from the public verification-key hash (which is already public on-chain), so it's safe for logs while still letting you tell two keys apart.

  • __str__ now delegates to __repr__, so both are redacted.

  • The fingerprint helper never raises — a repr that throws would break debuggers and logging.

What does not change

Deliberate export paths are untouched: to_json(), to_cbor(), and save() still return/write the real key material. A warning was added to to_json() documenting that its output contains secret material. Verification keys are unaffected.

Tests

New tests in test/pycardano/test_key.py confirm repr/str never contain the private bytes, the fingerprint is stable and public-derived, and the export methods still work.

`__repr__` and `__str__` on signing keys previously delegated to
`to_json()`, which embeds the raw CBOR hex of the private key. This
caused the secret to leak in logs, exception tracebacks, debugger
output, f-strings, and REPL echo.

Add `_IS_SECRET = True` to `SigningKey` and `ExtendedSigningKey` (and
thus all concrete payment/stake/pool subclasses). Override `__repr__` to
emit a redacted placeholder containing only the class name, key type,
and a non-reversible 16-hex-char fingerprint derived from the public
verification key hash. `__str__` delegates to the same path.

`to_json()`, `to_cbor()`, and `save()` are untouched — callers who
invoke those have opted in to exporting key material.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.75%. Comparing base (46382fd) to head (76441b3).
⚠️ Report is 38 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #494      +/-   ##
==========================================
+ Coverage   90.62%   90.75%   +0.12%     
==========================================
  Files          34       37       +3     
  Lines        5154     5367     +213     
  Branches      781      808      +27     
==========================================
+ Hits         4671     4871     +200     
- Misses        304      308       +4     
- Partials      179      188       +9     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cffls

cffls commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Code looks good. There is a format issue that could be fixed with make format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants